package com.cqhfan.contentservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqhfan.api.clients.interaction.LikedRecordClient;
import com.cqhfan.api.clients.user.UserClient;
import com.cqhfan.contentservice.mapper.CommentMapper;
import com.cqhfan.contentservice.service.CommentService;
import com.cqhfan.contentservice.service.WorksService;
import com.cqhfan.core.constans.MqConstants;
import com.cqhfan.core.domain.dto.PageDTO;
import com.cqhfan.core.enums.SystemMessageTypeEnum;
import com.cqhfan.core.exceptions.BizException;
import com.cqhfan.core.utils.UserContext;
import com.cqhfan.core.utils.UuidContextHolder;
import com.cqhfan.mq.strategy.MqMessageHelper;
import com.cqhfan.pojo.content.dto.AddCommentDTO;
import com.cqhfan.pojo.content.po.Comment;
import com.cqhfan.pojo.content.po.Works;
import com.cqhfan.pojo.content.query.CommentQuery;
import com.cqhfan.pojo.content.vo.CommentVO;
import com.cqhfan.pojo.im.dto.SystemMessageDTO;
import com.cqhfan.pojo.user.po.User;
import com.cqhfan.redis.constants.RedisConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 眭传洪
 * @create 2025-08-13 23:47
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    private final UserClient userClient;

    private final LikedRecordClient likedRecordClient;

    private final MqMessageHelper mqMessageHelper;

    private final StringRedisTemplate stringRedisTemplate;

    private final WorksService worksService;

    @Override
    @Transactional
    public void addComment(AddCommentDTO body) {
        // 拷贝并设置基础属性
        Long userId = UserContext.getUser();
        Comment comment = BeanUtil.copyProperties(body, Comment.class);
        comment.setCommentQuantity(0);
        comment.setLikesQuantity(0);
        comment.setPublishTime(LocalDateTime.now());
        comment.setPublishUserId(userId);
        comment.setIfShow(Boolean.TRUE);
        save(comment);

        // 如果是在别人底下的评论，则总评论数需要+1
        Long parentId = comment.getParentId();
        if (parentId != null && parentId != 0) {
            Comment parentComment = getById(parentId);
            if (parentComment == null) {
                throw new BizException("父级评论不存在");
            }
            // 实际开发不建议这么写哈，我是为了方便
            lambdaUpdate()
                    .setSql("comment_quantity = comment_quantity + 1")
                    .eq(Comment::getId, parentId)
                    .update();
        }

        // 添加幂等性标志
        String uuid = UUID.fastUUID().toString(true);
        String key = RedisConstants.IM.SYSTEM_MESSAGE_IDEMPOTENT_KEY_PREFIX + uuid;
        stringRedisTemplate.opsForValue().set(key, RedisConstants.NULL_VALUE,
                RedisConstants.IM.SYSTEM_MESSAGE_IDEMPOTENT_TTL, TimeUnit.SECONDS);

        // 发送即时消息
        Long replyUserId = body.getReplyUserId();
        SystemMessageTypeEnum systemMessageType = replyUserId == null
                ? SystemMessageTypeEnum.COMMENT
                : SystemMessageTypeEnum.REPLY;
        Long receiveUserId = replyUserId;
        if (receiveUserId == null) {
            Works works = worksService.getByWorksId(body.getBizId());
            receiveUserId = works.getAuthor();
        }
        SystemMessageDTO systemMessage = SystemMessageDTO.builder()
                .senderUserId(userId)
                .receiveUserId(receiveUserId)
                .messageType(systemMessageType.getValue())
                .content(body.getContent())
                .worksId(body.getBizId())
                .commentId(comment.getId())
                .uuid(uuid)
                .loginUuid(UuidContextHolder.getUuid())
                .build();
        mqMessageHelper.sendMessage(
                MqConstants.EXCHANGE.SYSTEM_MESSAGE_SEND_EXCHANGE,
                null,
                systemMessage
        );
    }

    @Override
    public PageDTO<CommentVO> pageComment(CommentQuery query) {
        Long parentId = query.getParentId();
        Integer pageNum = query.getPageNum();
        Integer pageSize = query.getPageSize();
        Integer commentType = query.getCommentType();
        Long bizId = query.getBizId();
        if (commentType == null) {
            throw new BizException("评论类型不能为空");
        }
        if (parentId == null && bizId == null) {
            throw new BizException("父评论id和业务的id不能都为空");
        }

        // 查询相关评论
        Page<Comment> page = lambdaQuery()
                .eq(Comment::getIfShow, Boolean.TRUE)
                .eq(Comment::getCommentType, commentType)
                .eq(bizId != null, Comment::getBizId, bizId)
                .eq(Comment::getParentId, bizId != null ? 0L : parentId)
                .orderByAsc(Comment::getPublishTime)
                .page(new Page<>(pageNum, pageSize));
        List<Comment> records = page.getRecords();
        if (CollUtil.isEmpty(records)) {
            return PageDTO.empty();
        }

        // 获取发布和回复的用户的id
        Set<Long> userIds = new HashSet<>(records.size());
        for (Comment record : records) {
            userIds.add(record.getPublishUserId());
            userIds.add(record.getReplyUserId());
        }
        // 获取用户并处理map
        List<User> users = userClient.listByIds(userIds);
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, u -> u));

        // 查询点赞情况
        Set<Long> commentIds = records.stream().map(Comment::getId).collect(Collectors.toSet());
        Set<Long> likedCommentIds = likedRecordClient.listLikeStatus(commentIds);

        // 组装vo
        List<CommentVO> result = new ArrayList<>(records.size());
        for (Comment record : records) {
            CommentVO vo = BeanUtil.copyProperties(record, CommentVO.class);
            // 设置发布信息
            User publishUser = userMap.get(record.getPublishUserId());
            if (publishUser != null) {
                vo.setPublishUserNickName(publishUser.getNickName());
                vo.setPublishUserAvatar(publishUser.getAvatar());
            }
            // 设置回复信息
            User replyUser = userMap.get(record.getReplyUserId());
            if (replyUser != null) {
                vo.setReplyUserNickName(replyUser.getNickName());
                vo.setReplyUserAvatar(replyUser.getAvatar());
            }
            // 设置是否点赞
            vo.setIfLiked(likedCommentIds.contains(record.getId()));
            result.add(vo);
        }

        // 返回结果
        return PageDTO.of(page.getPages(), page.getTotal(), result);
    }
}
